package framework.model;

import java.util.*;
import java.awt.event.*;

import framework.ai.*;
import framework.utils.UserPreferences;

/**
 * @class GameModel
 * @author Michel Jansma
 * @version 0.1
 */
public class GameModel extends Model {

	private AbstractAIModule AIModule;
	
	private boolean AIRunning;
	
	private ArrayList<HashMap<String,String>> players;
	
	private Integer playerIndex;
	
	private String gameMessage;
	
	/**********************
	 *** GLOBAL METHODS ***
	 *********************/
	
	public GameModel() {
		this.players = new ArrayList<HashMap<String,String>>();
		this.players.add(null);
		this.setAIRunning(false);
	};
	
	public void doPlayerMove(int move) {
		this.doPlayerMove(this.getPlayerIndex(), move);
	};
	
	public void doPlayerMove(int player, int move) {
		this.getAIModule().doMove(player, move);
		this.setCurrentPlayer(this.getAIModule().getOpponent());
		this.update("board");
	};
	
	public boolean isValidMove(int move) {
		return this.getAIModule().isValidMove(this.getPlayerIndex(), move);
	};
	
	public int bestMove() {
		return this.getAIModule().getBestMove(this.getPlayerIndex());
	};
	
	/**********************
	 *** SETTER METHODS ***
	 *********************/
	
	public void setAIRunning(boolean running) {
		this.AIRunning = running;
		this.update("autoplay");
	};
	
	public void setGameMessage(String message) {
		this.gameMessage = message;
		this.update("game_message");
	};
	
	public void setCurrentPlayer(int index) {
		this.getAIModule().setCurrentPlayer(index);
	};
	
	public void setBoardSize(int width, int height) {
		this.getAIModule().setBoard(width, height);
		this.getAIModule().initBoard();
	};
	
	public void setPlayer(String username, String resource) {
		HashMap<String, String> player = new HashMap<String,String>();
		player.put("username", username);
		player.put("resource", resource);
		this.players.add(player);
	};
	
	public void setAIModule(AbstractAIModule AIModule) {
		this.AIModule = AIModule;
	};
	
	public void setPlayerIndex(Integer index) {
		this.playerIndex = index;
	};
	
	/**********************
	 *** UPDATE METHODS ***
	 *********************/
	
	public void update(String command) {
		super.dispatchEvent(new ActionEvent(this,0, command + "_updated"));
	};
	
	public void updatePlayerIndex() {
		String username = UserPreferences.getProperty("username").toString();
		this.setPlayerIndex(this.getPlayerIndex(username));
	};

	/**********************
	 *** GETTER METHODS ***
	 *********************/

	public boolean getAIRunning() {
		return this.AIRunning;
	};
	
	public ArrayList<HashMap<String,String>> getPlayers() {
		return this.players;
	};
	
	public HashMap<String,String> getPlayer(int index) {
		if(index > -1 && index < this.players.size()) {
			return this.players.get(index);		
		} 
		return null;
	};
	
	public Integer getPlayerIndex() {
		return this.playerIndex;
	};
	
	public Integer getPlayerIndex(String username) {
		Integer index = null;
		for(int i = 0; i < this.players.size() && index == null; i++) {
			HashMap<String,String> player = this.players.get(i);
			if(player != null) {
				if(player.get("username").equals(username)) {
					index = i;
				};	
			};
		};
		return index;
	};
	
	public AbstractAIModule getAIModule() {
		return this.AIModule;
	};
	
	public int[][] getBoard() {
		return this.getAIModule().getBoard();
	};
	
	public int getBoardWidth() {
		return this.getAIModule().getWidth();
	};
	
	public int getBoardHeight() {
		return this.getAIModule().getHeight();
	};
	
	public String getGameType() {
		return this.getAIModule().getGameType();
	};
	
	public String getSettingsFile() {
		return this.getGameType().toLowerCase().replace(" ", "") + ".json";
	};
	
	public String getGameMessage() {
		return this.gameMessage;
	};
	
	public int board2DToId(int x, int y) {
		return (y*this.getAIModule().getHeight())+x;
	};

}
